package com.hfzy.ihk.web.freeswitchManage.biz;

import com.hfzy.ihk.common.util.string.StringTools;
import com.hfzy.ihk.facade.freeswitchManage.entity.Gateway;
import com.hfzy.ihk.facade.freeswitchManage.entity.GatewayCardSlot;
import com.hfzy.ihk.facade.freeswitchManage.entity.GatewayCardSlotHistory;
import com.hfzy.ihk.facade.freeswitchManage.entity.SwxCallLimitLog;
import com.hfzy.ihk.facade.freeswitchManage.enums.CardStatusEnum;
import com.hfzy.ihk.facade.freeswitchManage.enums.GatewayStateEnum;
import com.hfzy.ihk.facade.freeswitchManage.enums.GatewayTypeEnum;
import com.hfzy.ihk.facade.freeswitchManage.enums.SlotStateEnum;
import com.hfzy.ihk.web.freeswitchManage.mapper.GatewayCardSlotHistoryMapper;
import com.hfzy.ihk.web.freeswitchManage.mapper.GatewayCardSlotMapper;
import com.hfzy.ihk.web.freeswitchManage.mapper.GatewayMapper;
import com.hfzy.ihk.web.freeswitchManage.mapper.SwxCallLimitLogMapper;
import com.hfzy.ihk.web.freeswitchManage.support.base.AbstractEquipmentControlProcess;
import com.hfzy.ihk.web.freeswitchManage.support.swx.SwxEquipmentControlProcess;
import com.hfzy.ihk.web.freeswitchManage.vo.EquimentInfo;
import com.hfzy.ihk.web.freeswitchManage.vo.EquimentSlotInfo;
import com.hfzy.ihk.web.freeswitchManage.vo.GatewayCardSlotVo;
import com.hfzy.ihk.web.freeswitchManage.vo.RedisData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**czs
 * 设备推送信息处理业务类
 */
@Component
@Slf4j
public class EquipmentInfoBiz {

    @Autowired
    GatewayMapper gatewayMapper;

    @Autowired
    GatewayCardSlotMapper gatewayCardSlotMapper;

    @Autowired
    PushToWebsocketBiz pushToWebsocketBiz;

    @Autowired
    SwxCallLimitLogMapper swxCallLimitLogMapper;

    @Autowired
    GatewayCardSlotHistoryMapper gatewayCardSlotHistoryMapper;

    @Autowired
    SwxEquipmentControlProcess swxEquipmentControlProcess;



    /**
     * 开机时自动生成设备信息
     * 先查下是否存在该设备，如果存在则跳过，不存在就生成一条记录
     */
    @Transactional
    public void createEquipment(EquimentInfo equimentInfo){
        try{
            if(equimentInfo.getSn()==null){
                log.info(">>>>>>>设备注册sn为空");
                return ;
            }

            Gateway gateway = gatewayMapper.queryGatewayByNum(equimentInfo.getSn());
            if(gateway!=null){
                log.info(">>>>>>.设备已经初始化过：{}",equimentInfo.getSn());
            }else{
                Gateway _gateway = new Gateway();

                _gateway.setNum(equimentInfo.getSn());
                _gateway.setEquipment(equimentInfo.getEquipmentDealer());
                _gateway.setChannelNum(equimentInfo.getChannelNumber());
                _gateway.setCreateTime(new Date());
                _gateway.setCreateUserId(7);
                _gateway.setCreateUserName("系统管理员");
                _gateway.setState(GatewayStateEnum.ENABLE);
                _gateway.setType(GatewayTypeEnum.VOIP_01);
                _gateway.setPort("5060");
                gatewayMapper.insert(_gateway);
            }

            //保存后先生成历史表


            //保存之后删除该设备的所有卡槽数据，然后发送查询命令查询所有的卡槽状态和卡信息
            gatewayCardSlotMapper.delCardslotBySn(equimentInfo.getSn());
            //删除之后查询
            //查询所有卡槽信息
            Boolean rs=pushToWebsocketBiz.queryDevicesInfo(equimentInfo.getSn());
            log.info("query Devices rs:{}",rs);

            //查询freeswitch中继信息 获取 SipAddr, SipPort, AuthUser
            Boolean rs1=pushToWebsocketBiz.checFreeswitchkTrunk(equimentInfo.getSn());
            log.info("query Trunk rs:{}",rs1);
        }catch (Exception e){
            log.error(">>>>>>>生成设备信息失败sn：{}",equimentInfo.getSn(),e);
        }

    }


    /**
     * 换卡或者插卡的时候生成卡槽信息
     * 先查下是否已经存在该卡槽，如果存在就更新，否则生成
     */
    @Transactional
    public void createSolt(EquimentSlotInfo equimentSlotInfo) {

        try {
            if (StringTools.isEmpty(equimentSlotInfo.getSn())) {
                log.info(">>>>>>>>>>注册卡时sn码为空");
                return;
            }

            if (StringTools.isEmpty(equimentSlotInfo.getSlotId())||StringTools.isEmpty(equimentSlotInfo.getChannel())) {
                log.info(">>>>>>>>>>注册卡时通道号或者卡槽位为为空，soltId{},channel:{}",
                        equimentSlotInfo.getSlotId(), equimentSlotInfo.getChannel());
                return;

            }

            //判断在系统中是否曾经该卡槽记录
            GatewayCardSlot gatewayCardSlot = gatewayCardSlotMapper
                    .queryGatewayCardSlotBySnAndSoltIndxAndChannel(equimentSlotInfo.getSn(), equimentSlotInfo.getSlotId(), equimentSlotInfo.getChannel());

            if (gatewayCardSlot != null) { //已存在该卡槽

                if (CardStatusEnum.UP.getValue()
                        .equals(equimentSlotInfo.getStatus().getValue())) { //插卡

                    gatewayCardSlotMapper.updateCardInfoWhenUp(equimentSlotInfo.getSn(), equimentSlotInfo.getSlotId(),
                                                               equimentSlotInfo.getChannel(),SlotStateEnum.INSERT.getValue());

                    log.info(">>插卡成功，sn:{},channel:{},soltId:{}"
                            , equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId());

                } else if (CardStatusEnum.DOWN.getValue()
                        .equals(equimentSlotInfo.getStatus().getValue())) { //拔卡

                    gatewayCardSlotMapper.updateCardInfoWhenDown(equimentSlotInfo.getSn(), equimentSlotInfo.getSlotId(),
                            equimentSlotInfo.getChannel(),SlotStateEnum.BLANK.getValue());


                    log.info(">>拔卡成功 开始推送消息给设备清除该卡槽呼叫次数统计，sn:{},channel:{},soltId:{},ccid:{}"
                            , equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId(), equimentSlotInfo.getCcid());

                } else {

                    log.info(">>识别到错误插拔卡信息，不属于插也不属于拨");

                }
            } else { //不存在的卡槽，生成卡槽并且生成卡信息,一般这种情况不存在
                GatewayCardSlot _gatewayCardSlot = new GatewayCardSlot();

                _gatewayCardSlot.setChannel(equimentSlotInfo.getChannel());
                _gatewayCardSlot.setGatewayNum(equimentSlotInfo.getSn());
                _gatewayCardSlot.setSlotIndex(equimentSlotInfo.getSlotId());
                _gatewayCardSlot.setSlotState(SlotStateEnum.INSERT);
                gatewayCardSlotMapper.insert(_gatewayCardSlot);

                log.info(">>>>>>>>>>插卡卡成功，sn:{},channel:{},soltId:{},ccid:{}"
                       , equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId(), equimentSlotInfo.getCcid());
            }

        }catch (Exception e){
            log.error("更新卡槽信息失败sn：{},ccid:{}", equimentSlotInfo.getSn(), equimentSlotInfo.getCcid(),e);
        }

    }

    /**
     * 激活卡,激活当前卡之前，先把当前通道的其他卡先失效
     * @param equimentSlotInfo
     */
    @Transactional
    public void activeSolt(EquimentSlotInfo equimentSlotInfo) {
        try{
            if (StringTools.isEmpty(equimentSlotInfo.getSn())) {
                log.info(">>>>>>>>>>激活卡时sn码为空");
                return;
            }

            if (CardStatusEnum.ACTIVE.getValue().equals(equimentSlotInfo.getStatus().getValue())
                    &&StringTools.isEmpty(equimentSlotInfo.getCcid())) { //如果为激活卡，必须存在ccid
                log.info(">>>>>>>>>>激活卡时ccid码为空：{}", equimentSlotInfo.getSn());
                return;

            }
            //激活前获取当前通道的城市,sipUser 等信息，然后放入redis
            RedisData redisData = new RedisData();
            redisData.setTrunkName("swx"+equimentSlotInfo.getChannel());
            redisData.setSn(equimentSlotInfo.getSn());
            redisData.setSlotId(equimentSlotInfo.getSlotId());
            redisData.setChannel(equimentSlotInfo.getChannel());
            swxEquipmentControlProcess.updateChannelSlotStateMap(redisData);

            //保存最后激活信息
            try {
                gatewayCardSlotHistoryMapper.saveOrUpdateGatewayCardSlotHistory(equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId(), equimentSlotInfo.getCcid());
            }catch (Exception e){
                log.error(">>保存最后激活信息失败",e);
            }

            //激活前需要判断该卡槽是否是上一次就是这张卡的
            try {
                GatewayCardSlotHistory gatewayCardSlotHistory = gatewayCardSlotHistoryMapper.queryGatewayCardSlotHistoryBySlotInfo(equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId());
                if (gatewayCardSlotHistory != null && !equimentSlotInfo.getCcid().equals(gatewayCardSlotHistory.getCcid())) {
                    //不是同一张卡清楚该卡的统计信息
                    Boolean bl = pushToWebsocketBiz.ClearSlotStatis(equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId());

                    log.info(">>推送清除卡槽统计次数消息成功sn:{},channel:{},soltId:{}"
                            , equimentSlotInfo.getSn(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId());

                }
            }catch (Exception e){
                log.error(">>执行清楚统计次数逻辑异常",e);
            }

            //激活的时候需要判断一下该卡槽是否已经存在，避免卡槽信息比激活信息慢回来的情况
            GatewayCardSlot gatewayCardSlot = gatewayCardSlotMapper
                    .queryGatewayCardSlotBySnAndSoltIndxAndChannel(equimentSlotInfo.getSn(), equimentSlotInfo.getSlotId(), equimentSlotInfo.getChannel());

            if (gatewayCardSlot != null) { //已存在该卡槽 ，更新当前卡激活状态
                //将前一张已激活的卡更新为未激活
                gatewayCardSlotMapper.updateCardslotNotActiveState( equimentSlotInfo.getSn(),equimentSlotInfo.getChannel(), SlotStateEnum.INSERT.getValue());

                //更新当前卡为激活
                gatewayCardSlotMapper.updateCardslotActiveState(equimentSlotInfo.getSn(), equimentSlotInfo.getSlotId(), equimentSlotInfo.getChannel(), equimentSlotInfo.getCcid(), SlotStateEnum.ACTIVE.getValue() );

            }else{//不存在卡槽 插入 这种情况一般不存在，除非激活状态比卡槽信息早回来
                GatewayCardSlot _gatewayCardSlot = new GatewayCardSlot();
                _gatewayCardSlot.setSlotIndex(equimentSlotInfo.getSlotId());
                _gatewayCardSlot.setGatewayNum(equimentSlotInfo.getSn());
                _gatewayCardSlot.setChannel(equimentSlotInfo.getChannel());
                _gatewayCardSlot.setCcid(equimentSlotInfo.getCcid());
                _gatewayCardSlot.setSlotState(SlotStateEnum.ACTIVE);
                gatewayCardSlotMapper.insert(_gatewayCardSlot);
            }

        }catch (Exception e){
            log.error("激活卡槽失败sn：{},ccid:{},Channel:{},SlotId:{}",
                    equimentSlotInfo.getSn(), equimentSlotInfo.getCcid(), equimentSlotInfo.getChannel(), equimentSlotInfo.getSlotId(),e);
        }
    }

    /**
     * 生成设备所有卡槽信息，这里不需要事务，避免存在激活消息比卡槽信息早回来的情况，通过数据库的唯一来控制正确性。
     * @param equimentSlotInfos
     */
    public void createSoltInfo(List<EquimentSlotInfo> equimentSlotInfos) {
        if(StringTools.isEmpty(equimentSlotInfos))
            return;
        //批量生成卡槽和是否有卡数据
        for(EquimentSlotInfo equimentSlotInfo:equimentSlotInfos){
            try {
                int count = gatewayCardSlotMapper.saveOrUpdate(equimentSlotInfo,equimentSlotInfo.getSlotState().getValue());
                log.info("save count:{} ",count);
            }catch (Exception e){
                log.error(">>保存卡槽信息失败，data:{}",equimentSlotInfo.toString(),e);
            }
        }

    }


    /**
     * 当收到呼叫限制通知的时候将卡状态更新为：已插卡但是被限制的状态
     * ,这里也不需要事务，保存日志没有更新状态重要
     * @param equimentSlotInfo
     */
   // @Transactional
    public void dealCallLimit(EquimentSlotInfo equimentSlotInfo){
        try {
             int rs = gatewayCardSlotMapper.updateSlotState(equimentSlotInfo.getSn(),equimentSlotInfo.getChannel(),equimentSlotInfo.getSlotId(),SlotStateEnum.INSERT_LIMIT.getValue());
            log.info("更新呼叫限制并开始保存日志rs:{},data:{}",rs,equimentSlotInfo.toString());

            SwxCallLimitLog swxCallLimitLog = new SwxCallLimitLog();
            swxCallLimitLog.setGatewayNum(equimentSlotInfo.getSn());

            swxCallLimitLog.setChannel(equimentSlotInfo.getChannel());
            swxCallLimitLog.setSlotIndex(equimentSlotInfo.getSlotId());
            swxCallLimitLog.setLimitType(equimentSlotInfo.getInfo());
            swxCallLimitLogMapper.insert(swxCallLimitLog);
        }catch (Exception e){
            log.error(">>更新呼叫限制出错：{}",equimentSlotInfo.toString(),e);
        }
    }


    public void updateFreeswitchInfo(String num,String sipAddr,String sipPort,String authUser){
        try {
            gatewayMapper.updateSipUserAndIpAndPortByNum(num, authUser, sipAddr, sipPort);
        }catch (Exception e){
            log.error(">>更新freeswitch 中继信息失败：num：{},sipAddr:{},sipPort:{},authUser:{}",num,sipAddr,sipPort,authUser,e);
        }
    }


    /**
     * 将设备状态写redis逻辑，每一个呼叫的通道改变的状态
     * @param swxEquipmentControlProcess
     * @param redisData
     */
    public void createRedisData(AbstractEquipmentControlProcess swxEquipmentControlProcess, RedisData redisData){
        swxEquipmentControlProcess.dealChannelStatus(redisData);

    }


    /**
     * 将设备状态写redis逻辑,通过job 去自动获取的每个通道的状态
     * @param swxEquipmentControlProcess
     * @param redisData
     */
    public void checkQueueIdle(AbstractEquipmentControlProcess swxEquipmentControlProcess, RedisData redisData){
        swxEquipmentControlProcess.checkQueueIdle(redisData);

    }


}
